﻿using System;
using System.Collections.Generic;

namespace Flagwind.Data
{
	internal class MemberAccessor : IMemberAccessor
	{
		private static Dictionary<string, INamedMemberAccessor> accessorCache = new Dictionary<string, INamedMemberAccessor>();

		public object GetValue(object instance, string memberName)
		{
			return FindAccessor(instance, memberName).GetValue(instance);
		}

		public void SetValue(object instance, string memberName, object newValue)
		{
			FindAccessor(instance, memberName).SetValue(instance, newValue);
		}

		public INamedMemberAccessor FindAccessor<T>(string memberName) where T : class
		{
			var type = typeof(T);
			return FindAccessor(type, memberName);
		}

		private INamedMemberAccessor FindAccessor(object instance, string memberName)
		{
			var type = instance.GetType();
			return FindAccessor(type, memberName);
		}

		private INamedMemberAccessor FindAccessor(Type type, string memberName)
		{
			return FindAccessor(type, memberName, true);
		}

		/// <summary>
		/// 在指定的类型中寻找指定属性名称的属性访问器，如果找不到返回空。
		/// </summary>
		/// <param name="type">对象类型</param>
		/// <param name="memberName">属性名称</param>
		/// <returns>属性访问起 </returns>
		public INamedMemberAccessor TryFindAccessor(Type type, string memberName)
		{
			return FindAccessor(type, memberName, false);
		}

		private INamedMemberAccessor FindAccessor(Type type, string memberName, bool throwError)
		{
			var key = type.FullName + memberName;
			INamedMemberAccessor accessor;
			accessorCache.TryGetValue(key, out accessor);
			if(accessor == null)
			{
				var propertyInfo = type.GetProperty(memberName);
				if(propertyInfo == null)
				{
					if(throwError)
					{
						throw new ArgumentException("实体类中没有属性名为" + memberName + " 的属性！");
					}
					else
					{
						return null;
					}
				}
				accessor = Activator.CreateInstance(typeof(PropertyAccessor<,>).MakeGenericType(type, propertyInfo.PropertyType), type, memberName) as INamedMemberAccessor;
				accessorCache.Add(key, accessor);
			}
			return accessor;
		}
	}
}